package com.trgis.yhmap.util.wmtsproxy.service;

import com.trgis.yhmap.util.wmtsproxy.bean.HttpPooling;
import com.trgis.yhmap.util.wmtsproxy.exception.ExceptionMsg;
import com.trgis.yhmap.util.wmtsproxy.WmtsXMLReader;
import com.trgis.yhmap.util.wmtsproxy.exception.WmtsConfigException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * @author wangfy
 * 2022年2月15日 修复http连接资源没有及时释放的问题，使用http连接池
 */
@Service
public class WMTSService {
    private static final Logger log = LoggerFactory.getLogger(WMTSService.class);

    private final WmtsXMLReader reader = WmtsXMLReader.getReader();

    private final HttpPooling httpPooling;

    public WMTSService(HttpPooling httpPooling) {
        this.httpPooling = httpPooling;
    }

    //    @Cacheable(value = "tile", key = "#request.getQueryString()")
    public byte[] getTile(String layer, HttpServletRequest request) throws URISyntaxException, WmtsConfigException {
        URI uri = new URIBuilder(reader.getUrl(layer, request)).build();
        // 获取到真实的请求地址和参数
        HttpGet httpGet = new HttpGet(uri);
        try (CloseableHttpResponse response = httpPooling.getHttpClient(uri.getHost(), uri.getPort()).execute(httpGet)){
            int statusCode = response.getStatusLine().getStatusCode();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            response.getEntity().writeTo(byteArrayOutputStream);
            if (HttpStatus.OK.value() == statusCode) {
                httpGet.abort();
                return byteArrayOutputStream.toByteArray();
            } else {
                response.close();
                httpGet.abort();
                throw new WmtsConfigException(ExceptionMsg.tileOutOfRange, byteArrayOutputStream.toString().replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>",""));
            }
        } catch (IOException e) {
            e.printStackTrace();
            httpGet.abort();
            throw new WmtsConfigException(ExceptionMsg.remoteException, "地图服务器异常");
        }
    }

    public byte[] getTileRest(String layer, String style, String tileMatrixSet, String tileMatrix, int tileRow, int tileCol, String format) throws WmtsConfigException {
        // 获取到真实的请求地址和参数
        String url = reader.getRestUrl(layer, style, tileMatrixSet, tileMatrix, tileRow, tileCol, format);
        URI uri;
        try {
            uri = new URIBuilder(url).build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
            throw new WmtsConfigException(ExceptionMsg.URISyntaxException, "地图服务地址配置错误");
        }
        try (CloseableHttpResponse response = httpPooling.getHttpClient(uri.getHost(), uri.getPort()).execute(new HttpGet(uri))){
            int statusCode = response.getStatusLine().getStatusCode();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            response.getEntity().writeTo(byteArrayOutputStream);
            if (HttpStatus.OK.value() == statusCode) {
                return byteArrayOutputStream.toByteArray();
            } else {
                log.error("地址 {}，没有取到瓦片", url);
                response.close();
                throw new WmtsConfigException(ExceptionMsg.remoteException, byteArrayOutputStream.toString().replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>",""));
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new WmtsConfigException(ExceptionMsg.remoteException, "地图服务器异常");
        }
    }
}
